<?php
namespace app\crontab\controller;

use think\Controller;
use think\facade\Log;
use app\common\controller\Common;
use app\common\controller\CustomOutput;
use app\common\model\Daynote as DaynoteModel;
use app\common\model\Config as ConfigModel;
use app\common\model\UserWx as UserWxModel;

/**
 * 消息推送
 * 此处做参考，具体执行通过sh指令执行app\crontab\command\WxPushMessage
 * @author hjx
 **/

class WxPushMessage extends Controller
{
    private $getAccessTokenUrl;
    private $subscribeMessageUrl;
    
    private $commonCtl;
    private $coutHandler;
    
    private $daynoteModel;
    private $configModel;
    private $userWxModel;
    
    public function __construct() {
        parent::__construct();
        
        $this->commonCtl = new Common();
        $this->coutHandler = new CustomOutput();
        
        $this->daynoteModel = new DaynoteModel();
        $this->configModel = new ConfigModel();
        $this->userWxModel = new UserWxModel();
    }
    
    // 构造
    private function makeGetAccessTokenUrl() {
        $this->getAccessTokenUrl = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . config('custom.wxAppid') . '&secret=' . config('custom.wxAppSecret');
    }
    
    // 构造
    private function makeSubscribeMessageUrl($access_token) {
        $this->subscribeMessageUrl = 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=' . $access_token;
    }
    
    // 获取access token
    /**
     * step1: 判断数据库中是否存储access token，是否过期
     * step2: 未过期则返回access token
     * step3: 过期则重新获取并更新到数据库
     **/
    private function getAccessToken() {
        Log::write(date('Y-m-d H:i:s') . ': 正在获取access token', 'info');
        // step1
        $access_token = $this->configModel->get('wx_access_token')->config_value;
        $exp_time = $this->configModel->get('wx_access_token_expire_time')->config_value;
        
        if($access_token != NULL && $exp_time != NULL && date('Y-m-d H:i:s') < $exp_time){
            Log::write(date('Y-m-d H:i:s') . ': access token未过期', 'info');
            // step2
            // 已存在且未过期
            return $access_token;
        }else{
            Log::write(date('Y-m-d H:i:s') . ': access token重新获取中', 'info');
            // step3
            // 不存在或已过期
            $this->makeGetAccessTokenUrl();
            $res = $this->commonCtl->commonCurlGet($this->getAccessTokenUrl);
            if(isset($res['access_token']) && isset($res['expires_in'])){
                echo $res['access_token'] . ':' . $res['expires_in'];
                $token_expire_time = date('Y-m-d H:i:s', (time() + $res['expires_in'] - 300)); // 将过期时间提前5分钟
                $this->configModel->save(array('config_value' => $res['access_token']), array('config_name' => 'wx_access_token'));
                $this->configModel->save(array('config_value' => $token_expire_time), array('config_name' => 'wx_access_token_expire_time'));
                Log::write(date('Y-m-d H:i:s') . ': access token重新获取获取成功','info');
                return $res['access_token'];
            }else{
                Log::write(date('Y-m-d H:i:s') . ': access token获取错误', 'info');
                Log::write($res['errcode'] . ':' . $res['errmsg'], 'info');
                $this->coutHandler->outputJson($res['errcode'] . ':' . $res['errmsg'], 250);
            }
        }
    }
    
    /**
     * 发送日程提醒
     * step1: 查看数据库中的日程,当前时间半小时以后的日程
     * step2: 拼装数据，发送提醒
     **/
    private function sendWxMessage() {

        Log::write(date('Y-m-d H:i:s') . ': 发送日程提醒开始', 'info');
        
        $pwd = $this->request->param('key', '');
        
        if($pwd != config('custom.crontabPwd')){
            Log::write('密码错误', 'error');
            echo '错误';
            exit();
        }
        
        // step1
        $daynoteIds = $this->daynoteModel
            ->field('id, user_id, content, rtime')
            ->whereTime('rtime', '>', date('Y-m-d H:i:s'))
            ->whereTime('rtime', '<=', date('Y-m-d H:i:s', time() + 1800))
            ->select();
        
        $access_token = $this->getAccessToken();
        $this->makeSubscribeMessageUrl($access_token);
        
        // step2
        foreach ($daynoteIds as $v){
            $openid = $this->userWxModel->where('user_id', $v['user_id'])->find()->openid;
            $data = array();
            $data['touser'] = $openid;
            $data['template_id'] = '-Xhsa9YapQ5WIkpb26odUmKgELceU3O74J12JZHmcHA';
            $data['data'] = array(
                'character_string2' => array('value' => $v['rtime']),
                'thing4' =>  array('value' => $v['content'])
            );
            $res = $this->commonCtl->commonCurlPost($this->subscribeMessageUrl, json_encode($data));
            
            Log::write(date('Y-m-d H:i:s') . ': ' . $res, 'info');
        }
        
        Log::write(date('Y-m-d H:i:s') . ': 发送日程提醒结束', 'info');
        echo '正常执行';
        exit();
    }
}
